<script lang="ts" setup name="ApprovalEndorse">
import { Link, Plus, View } from '@element-plus/icons-vue'
import { IkingPicker } from 'iking-web-ui'
import type { endorseFormState } from '../interface'
import {
  aggreeReply,
  ApprovalBtnType,
  ApprovalTypeLabel,
  ApprovalTypePlaceholder,
  ENodeType,
  rejectReply
} from './dict'
import { approvalApi } from '@/MainApp/apis/approval'

const props = defineProps({
  visible: {
    type: Boolean,
    default: false
  },
  approvalType: {
    type: String,
    default: () => 'endorse'
  },
  instanceUserType: {
    type: String,
    default: () => 'ALL'
  },
  editData: {
    type: Object,
    default: () => null
  }
})
const emits = defineEmits<{
  (e: 'update:visible', bool: boolean): void
  (e: 'handleConfirm', value: any): void
}>()

// 新增、修改
const placeholder = {
  appendExecutorUserIds: '请选择加签审批人',
  approveComment: '请输入加签意见',
  appendType: '请选择加签方式',
  careOfUserIds: '请选择转交对象',
  careOfComment: '请输入转交理由',
  backToInstanceNodeId: '请选择退回节点',
  backComment: '请输入退回理由',
  denyComment: '请输入拒绝理由',
  agreeComment: '请输入同意理由'
}

const approvalEndorseState: any = reactive<endorseFormState>({
  title: '加签处理',
  loading: false,
  form: {
    formInstanceId: '',
    formData: '',
    appendType: 'BEFORE',
    appendExecutorUserIds: [],
    backToInstanceNodeId: '',
    formInstanceComment: '',
    approveComment: '',
    attachments: [],
    images: []
  }
})

const approveFlowStore = useApproveFlowStore()
const approvalEndorseRules = {
  appendType: [
    { required: true, message: placeholder.appendType, trigger: 'change' }
  ],
  approveComment: [
    { required: false, message: placeholder.approveComment, trigger: 'blur' }
  ],
  careOfUserIds: [
    { required: true, message: placeholder.careOfUserIds, trigger: 'change' }
  ],
  appendExecutorUserIds: [
    {
      required: true,
      message: placeholder.appendExecutorUserIds,
      trigger: 'change'
    }
  ],
  backToInstanceNodeId: [
    {
      required: true,
      message: placeholder.backToInstanceNodeId,
      trigger: 'change'
    }
  ]
}
const approvalEndorseRef = ref()
const dVisible = ref(false)
const len_content = 200

const token = useToken()
const { uploadUrl, loadUrl, baseUrl, setFileUrl } = useHttpUrl()

const dialogImageUrl = ref('')
const dialogVisible = ref(false)
const c_type = {
  all: ['user'], // ['dep', 'user', 'role', 'post'],
  user: ['user']
}
const showPicker = ref(false)
const chooseType = ref(c_type.all)
const echoData: Ref<any[]> = ref([])
const instanceNodeList: Ref<any[]> = ref([])
const userList = ref([])

const handleClose = () => {
  emits('update:visible', false)
  approvalEndorseState.loading = false
  approvalEndorseRef.value?.resetFields()
  approvalEndorseState.form = {}
}
const showApproveUserError = ref(false)
const handleConfirm = async () => {
  approvalEndorseRef.value.validate((valid: any) => {
    if (valid) {
      if (props.approvalType === 'sendBack') {
        const data = instanceNodeList.value.find(v => v.id === approvalEndorseState.form.backToInstanceNodeId)
        if (!approvalEndorseState.form.appendExecutorUserIds?.length && data?.type !== ENodeType.发起人节点) {
          showApproveUserError.value = true
          return
        }
      }
      emits('handleConfirm', approvalEndorseState.form)
      approvalEndorseRef.value?.resetFields()
      approvalEndorseState.form = {}
    }
  })
}
watch(() => approvalEndorseState.form.appendExecutorUserIds, val => {
  if (val.length)
    showApproveUserError.value = false
})

watch(
  () => props.visible,
  (bool: boolean) => {
    dVisible.value = bool
    showApproveUserError.value = false
    if (bool) {
      approvalEndorseState.title = ApprovalBtnType[props.approvalType as keyof typeof ApprovalBtnType]
      if (props.approvalType === 'sendBack')
        executedNode(approveFlowStore.rowData)
    }
  }
)

const handleRemove = (uploadFile: any, uploadFiles: any) => {
  approvalEndorseState.form.images = uploadFiles
}

const handlePictureCardPreview = (uploadFile: any) => {
  dialogImageUrl.value = uploadFile.url!
  dialogVisible.value = true
}

const handIconOpenSuccess = async (res: any) => {
  if (res?.success) {
    approvalEndorseState.form.attachments = [
      {
        attachmentId: res?.data?.id,
        attachmentName: res?.data?.originName,
        attachmentSuffix: res?.data?.suffix,
        attachmentSize: res?.data?.fileSize,
        name: res?.data?.originName,
        url: loadUrl + res?.data?.id
      } as never
    ]
  }
}
const uploadRef: Ref<any> = ref(null)
const handBeforeUpload = () => {
  if (approvalEndorseState.form.attachments.length)
    uploadRef.value?.handleRemove(approvalEndorseState.form.attachments[0])
  return true
}

const handChooseUser = async (val: number) => {
  if (val !== -1) {
    chooseType.value = c_type.user
    userList.value = instanceNodeList.value?.[val]?.executorUsers?.map((v: any) => {
      return {
        ...v,
        elementName: v.userName,
        elementId: v.userId,
        elementType: 'USER'
      }
    })
  }
  else {
    chooseType.value = c_type.all
    userList.value = []
  }

  echoData.value = []
  showPicker.value = true
}
const deletePer = (index: any) => {
  // 删除人员
  approvalEndorseState?.form?.appendExecutorUserIds.splice(index, 1)
}
const replyBtnClick = (val: any) => {
  approvalEndorseState.form.approveComment = val
}
const executedNode = async (v: any) => {
  const { success, data } = await approvalApi.executedNode(v.id)
  if (success)
    instanceNodeList.value = data
}

const { msgError } = useMessage()
const handSuccess = (res: any, file: any, files: any) => {
  approvalEndorseState.form.images = files.filter((f: any) => f.response.success)
  if (!res.success)
    msgError(res.msg)
}
</script>

<template>
  <el-dialog
    v-model="dVisible"
    :title="approvalEndorseState.title"
    draggable
    width="683px"
    align-center
    :close-on-click-modal="false"
    :append-to-body="true"
    class="approval-endorse-cen"
    @closed="handleClose"
  >
    <el-form
      ref="approvalEndorseRef"
      :model="approvalEndorseState.form"
      :rules="approvalEndorseRules"
      label-width="100px"
    >
      <template v-if="props.approvalType === 'endorse'">
        <el-form-item label="加签审批人:" prop="appendExecutorUserIds">
          <!-- <el-input
            v-model="approvalEndorseState.form.appendExecutorUserIds"
            :maxlength="len_name"
            :placeholder="placeholder.appendExecutorUserIds"
            show-word-limit
          /> -->
          <div class="choise-user">
            <div v-for="(it, s) of approvalEndorseState?.form?.appendExecutorUserIds" :key="it.userId" class="list">
              <div>
                <div class="avatar">
                  <img v-if="it.userAvatar" :src="it.userAvatar" alt="">
                  <div v-else class="nodeBg">
                    <i class="iconfont ikflow-approve-ziyuan"></i>
                  </div>

                  <i class="iconfont ikflow-approve-shanchu1" @click="deletePer(s)"></i>
                </div>
                <div class="name">{{ it.elementName }}</div>
              </div>
              <!-- 显示添加人按钮,不是单选且已选中一个人的情况，显示图标 -->
              <span
                v-if="approvalEndorseState?.form?.appendExecutorUserIds?.length > 1
                "
                class="sign"
              >
                <span>{{
                  props.instanceUserType === 'ANY'
                    ? '/'
                    : props.instanceUserType === 'ALL'
                      ? '+'
                      : '>'
                }}</span>
              </span>
            </div>
            <div class="plus-btn">
              <el-icon :size="30" @click="handChooseUser(-1)">
                <Plus />
              </el-icon>
            </div>
          </div>
        </el-form-item>
        <el-form-item label="加签方式:" prop="appendType">
          <el-radio-group v-model="approvalEndorseState.form.appendType">
            <el-radio label="BEFORE">在我之前</el-radio>
            <el-radio label="AFTER">在我之后</el-radio>
          </el-radio-group>
          <IkColorText type="warning" class="tip-text mb-[3px]">
            在我之前：加签后，流程先经过被加签人，再由当前审批人处理
          </IkColorText>
          <IkColorText type="warning" class="tip-text">
            在我之后：加签后，流程会执行同意并加签
          </IkColorText>
        </el-form-item>
      </template>
      <template v-if="props.approvalType === 'sendBack'">
        <el-form-item label="退回节点:" prop="backToInstanceNodeId">
          <el-radio-group v-model="approvalEndorseState.form.backToInstanceNodeId" class="ml-4 back-radio-group" @change="showApproveUserError = false">
            <el-radio v-for="(item, index) in instanceNodeList" :key="index" :label="item?.id">
              <div class="choise-user choise-stype">
                <span>
                  {{
                    `${item?.name}(${index === 0 ? '上一' : `第${item?.sortOrder}`
                    }步)`
                  }}
                </span>
                <template v-if="item?.multiExecutorType === 'SEQUENCE'">
                  <div
                    v-for="(it, s) of approvalEndorseState?.form
                      .appendExecutorUserIds"
                    :key="it.userId"
                    class="list ml15"
                  >
                    <div>
                      <div class="avatar">
                        <img v-if="it.userAvatar" :src="setFileUrl(it.userAvatar)" alt="">
                        <div v-else class="nodeBg">
                          <i class="iconfont ikflow-approve-ziyuan"></i>
                        </div>
                        <i class="iconfont ikflow-approve-shanchu1" @click="deletePer(s)"></i>
                      </div>
                      <div class="name">{{ it.elementName }}</div>
                    </div>
                    <!-- 显示添加人按钮,不是单选且已选中一个人的情况，显示图标 -->
                    <span
                      v-if="approvalEndorseState?.form?.appendExecutorUserIds?.length > 1
                      "
                      class="sign"
                    >
                      <span>{{
                        props.instanceUserType === 'ANY'
                          ? '/'
                          : props.instanceUserType === 'ALL'
                            ? '+'
                            : '>'
                      }}</span>

                    </span>
                  </div>
                  <div class="plus-btn ml15">
                    <el-icon :size="30" @click="handChooseUser(index)">
                      <Plus />
                    </el-icon>
                    <div v-if="showApproveUserError" class="el-form-item__error">请选择节点审批人</div>
                  </div>
                </template>
              </div>
            </el-radio>
          </el-radio-group>
        </el-form-item>
      </template>
      <el-form-item
        :label="ApprovalTypeLabel[props.approvalType as keyof typeof ApprovalTypeLabel]"
        prop="approveComment"
      >
        <el-input
          v-model="approvalEndorseState.form.approveComment"
          type="textarea"
          :maxlength="len_content"
          :placeholder="ApprovalTypePlaceholder[props.approvalType as keyof typeof ApprovalTypePlaceholder]"
          :rows="8"
          show-word-limit
        />
      </el-form-item>
      <div v-if="props.approvalType === 'reject' || props.approvalType === 'agree'" class="upload-btn">
        <div class="recommend-reply">
          <span>推荐回复</span>
          <el-icon :size="18">
            <View />
          </el-icon>
        </div>
        <div v-if="props.approvalType === 'reject'" class="reply-cen">
          <el-button
            v-for="(item, index) in rejectReply"
            :key="index"
            class="reply-btn"
            type="info"
            plain
            @click="replyBtnClick(item)"
          >
            {{ item }}
          </el-button>
        </div>
        <div v-if="props.approvalType === 'agree'" class="reply-cen">
          <el-button
            v-for="(item, index) in aggreeReply"
            :key="index"
            class="reply-btn"
            type="info"
            plain
            @click="replyBtnClick(item)"
          >
            {{ item }}
          </el-button>
        </div>
      </div>
      <el-form-item label="上传图片:" prop="images">
        <el-upload
          v-model:file-list="approvalEndorseState.form.images"
          class="endorse-uploader"
          list-type="picture-card"
          :action="uploadUrl"
          accept="image/*"
          :on-preview="handlePictureCardPreview"
          :on-remove="handleRemove"
          :on-success="handSuccess"
        >
          <el-icon>
            <Plus />
          </el-icon>
        </el-upload>
        <el-dialog v-model="dialogVisible">
          <img w-full :src="dialogImageUrl" alt="Preview Image">
        </el-dialog>
      </el-form-item>
      <el-form-item label="上传文件:" prop="attachments">
        <el-upload
          ref="uploadRef"
          v-model:file-list="approvalEndorseState.form.attachments"
          class="upload-demo"
          :action="uploadUrl"
          :limit="2"
          :auto-upload="true"
          :before-upload="handBeforeUpload"
          :on-success="handIconOpenSuccess"
        >
          <template #trigger>
            <el-button :icon="Link" type="primary" plain>上传文件</el-button>
          </template>
          <template #tip>
            <div class="el-upload__tip text-red">
              只能上传一个文件，新的文件会覆盖之前的文件
            </div>
          </template>
        </el-upload>
      </el-form-item>
    </el-form>
    <IkingPicker
      ref="refIkingPicker"
      v-model="approvalEndorseState.form.appendExecutorUserIds"
      v-model:show="showPicker"
      :user-list="userList"
      :api="{
        methods: 'post',
        url: `${baseUrl}/server/component/pick/mix`,
        headers: {
          'Content-Type': 'application/json;charset=UTF-8',
          'Authorization': token,
        },
      }"
      :multiple="approvalType !== 'sendBack'"
      :tabs="['group']"
      :choose-type="chooseType"
      :type-option="{
        dep: 'DEPT',
        user: 'USER',
        role: 'ROLE',
        post: 'POST',
      }"
      :prop-option="{
        name: 'elementName',
        id: 'elementId',
        type: 'elementType',
      }"
    />
    <!-- <div class="upload-btn">
      <el-button type="info" plain :icon="Picture">上传图片</el-button>
    </div>
    <el-row class="upload-btn">
      <el-col :span="24"> 上传图片 </el-col>
      <el-col :span="24" class="cen-text">
        <el-upload
          class="endorse-uploader"
          v-model:file-list="fileList"
          list-type="picture-card"
          :action="uploadUrl"
          :on-preview="handlePictureCardPreview"
          :on-remove="handleRemove"
        >
          <el-icon><Plus /></el-icon>
        </el-upload>
        <el-dialog v-model="dialogVisible">
          <img w-full :src="dialogImageUrl" alt="Preview Image" />
        </el-dialog>
      </el-col>
      <el-col :span="24">
        <el-upload
          ref="upload"
          v-model:file-list="fileList"
          class="upload-demo"
          :action="uploadUrl"
          :limit="1"
          :auto-upload="true"
          :on-success="
            (res: any) => {
              handIconOpenSuccess(res, 'favicon')
            }
          "
        >
          <template #trigger>
            <el-button :icon="Link" type="info" plain>上传文件</el-button>
          </template>
          <template #tip>
            <div class="el-upload__tip text-red">
              只能上传一个文件，新的文件会覆盖之前的文件
            </div>
          </template>
        </el-upload>
      </el-col>
    </el-row> -->
    <template #footer>
      <el-button @click="handleClose"> 取消 </el-button>
      <el-button type="primary" :loading="approvalEndorseState.loading" @click="handleConfirm">
        确认
      </el-button>
    </template>
  </el-dialog>
</template>

<style lang="scss">
.approval-endorse-cen {
  .tip-text {
    position: relative;
    left: 0;
    top: 0;
  }

  .upload-btn {
    margin-left: 100px;

    .recommend-reply {
      color: #999;
      display: flex;
      align-items: center;
      justify-content: space-between;
    }

    .reply-cen {
      margin-bottom: 15px;

      .reply-btn {
        border: none !important;
        padding: 0 8px !important;
        margin: 10px 12px 0 0 !important;
      }
    }
  }

  .el-dialog__body {
    height: 80vh !important;
    padding: 24px !important;
    overflow: auto !important;
    flex: 1;

    .p_picker-dialog {
      .el-dialog__body {
        height: auto !important;

        .view-list {
          height: 565px !important;
        }
      }
    }
  }

  .cen-text {
    padding: 10px 0;
  }

  .choise-user {
    display: flex;
    justify-content: center;
    align-items: flex-start;
    cursor: pointer;
    transition: opacity .25s;

    &:hover{
      opacity: 0.75;
    }

    .list {
      display: flex;
      justify-content: center;
      align-items: flex-start;
      text-align: center;

      .avatar {
        width: 30px;
        height: 30px;
        border-radius: 50%;
        margin: auto;
        position: relative;
        overflow: hidden;

        img {
          width: 100%;
          height: 100%;
        }

        .nodeBg {
          display: inline-block;
          width: 100%;
          height: 100%;
          border-radius: 50%;
          background: #ccc;
          text-align: center;

          i:nth-child(1) {
            color: #ffff;
            line-height: 35px;
            font-size: 20px;
          }
        }

        >i {
          position: absolute;
          right: -5px;
          top: -8px;
        }
      }

      .sign {
        font-size: 14px;
        margin: 10px 5px 0;
      }

      .name {
        font-size: var(--el-font-size-extra-small);
      }
    }

    .plus-btn {
      margin-top: 5px;
      border: 1px dashed #409eff;
      border-radius: 3px;
      color: #409eff;
      width: 40px;
      height: 40px;
      display: flex;
      align-items: center;
      justify-content: center;
    }
  }

  .choise-stype {
    display: flex;
    justify-content: center;
    align-items: center;

    .ml15 {
      margin-left: 15px;
    }
  }

  .endorse-uploader {
    .el-upload-list__item {
      width: 86px !important;
      height: 86px !important;
    }

    .el-upload {
      width: 86px !important;
      height: 86px !important;
    }
  }
}

.back-radio-group {
  display: inline-flex;
  flex-flow: column wrap;
  font-size: 0;
  align-items: flex-start;

  label {
    margin-bottom: 8px;
  }
}
</style>
